package com.test.aop;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;

/**
 * @author lzy
 * @version v1.0
 * Create DateTime: 2018/9/27 16:30
 */
public class ArithmetricCalculatorLoggingProxy {
    // 要代理的对象
    private ArithmeticCalculator target;

    public ArithmetricCalculatorLoggingProxy(ArithmeticCalculator target) {
        this.target = target;
    }

    public ArithmeticCalculator getLoggingProxy() {
        ArithmeticCalculator proxy = null;
        //代理对象由哪一个类加载器负责加载
        ClassLoader classloader = target.getClass().getClassLoader();
        //代理对象类型，及其中有哪些方法
        Class[] interfaces = new Class[]{ArithmeticCalculator.class};

        InvocationHandler handler = new InvocationHandler() {
            /**
             * @param proxy: 正在返回的那个代理对象，一般情况下，在invoke方法中都不使用该对象
             * @param method: 正在被调用的方法
             * @param args: 调用方法时，传入的参数
             * @return
             * @throws Throwable
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                String methodName = method.getName();
                //以下是一个无限死循环
                //System.out.println(proxy.toString());
                //日志
                System.out.println("The method " + methodName + " begins with " + Arrays.toString(args));
                //执行方法
                Object result = null;

                try {
                    //前置通知
                    result = method.invoke(target, args);
                    //返回通知：可以访问到方法的返回值
                } catch (Exception e) {
                    e.printStackTrace();
                    //异常通知：可以访问到方法出现的异常
                }

                //后置通知，因为方法可能会出现异常，因此访问不到方法的返回值

                //日志
                System.out.println("The method " + methodName + " ends with result " + result);
                return result;
            }
        };

        proxy = (ArithmeticCalculator) Proxy.newProxyInstance(classloader, interfaces, handler);
        return proxy;
    }
}
